/**
 *    Copyright 2009-2019 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.reflection.property;

import java.util.Iterator;

/**
 * 属性令牌
 * 根据 . 分隔属性
 * 即将会将 user.jpanda.name依次解析为:
 * {
 * user:{
 * jpanda:{
 * name: 'jpanda'
 * }
 * }
 * }
 *
 * @author Clinton Begin
 */
public class PropertyTokenizer implements Iterator<PropertyTokenizer> {
    /**
     * 属性名称:
     * 比如names[0].first中的names
     * 比如names.first中的names
     */
    private String name;
    /**
     * 包含索引的名称，
     * 比如：names[0].first中的names[0]
     * 比如：names.first中的names
     */
    private final String indexedName;
    /**
     * 索引值
     * 比如：names[0].first中的0
     * 比如：names.first中的null
     */
    private String index;
    /**
     * 子属性
     * 比如：names[0].first中的first
     * 比如：panda.name.first中的name.first
     */
    private final String children;

    /**
     * 生成PropertyTokenizer对象
     *
     * @param fullname 完整的属性名称描述符
     */
    public PropertyTokenizer(String fullname) {
        // 假设入参为names[0].first

        // 获取第一个属性分隔符的位置
        int delim = fullname.indexOf('.');

        if (delim > -1) {
            // 有属性分隔符，表示是一个嵌套的多层属性
            // 获取属性分隔符前面的内容作为属性，此处是names[0]
            name = fullname.substring(0, delim);
            // 属性分隔符后面的内容，则作为子属性保存起来，此处是first
            children = fullname.substring(delim + 1);
        } else {
            // 当前不存属性分隔符，直接赋值即可
            name = fullname;
            children = null;
        }

        // 处理names[0].first这种包含了索引的场景
        // 包含索引内容的属性名称此处是names[0]
        indexedName = name;
        // 获取属性名称中[ 符号的位置
        delim = name.indexOf('[');
        if (delim > -1) {
            // 包含索引引用
            // 获取索引的值，表示从names[1]中获取1。
            index = name.substring(delim + 1, name.length() - 1);
            // 重新赋值，将names[0]转为names
            name = name.substring(0, delim);
        }
    }

    public String getName() {
        return name;
    }

    public String getIndex() {
        return index;
    }

    public String getIndexedName() {
        return indexedName;
    }

    public String getChildren() {
        return children;
    }

    @Override
    public boolean hasNext() {
        // 是否有children数据
        return children != null;
    }

    @Override
    public PropertyTokenizer next() {
        // 通过child生成新的PropertyTokenizer
        return new PropertyTokenizer(children);
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException("Remove is not supported, as it has no meaning in the context of properties.");
    }
}
